package com.mical.demo.config;

import com.mical.demo.security.JwtTokenFilter;
import com.mical.demo.security.JwtTokenUtil;
import com.mical.demo.service.TokenBlacklistService;
import com.mical.demo.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.context.DelegatingSecurityContextRepository;
import org.springframework.security.web.context.NullSecurityContextRepository;
import org.springframework.security.web.context.RequestAttributeSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextRepository;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final JwtTokenFilter jwtTokenFilter;
    private final TokenBlacklistService tokenBlacklistService;
    public SecurityConfig(JwtTokenFilter jwtTokenFilter, TokenBlacklistService tokenBlacklistService) {
        this.jwtTokenFilter = jwtTokenFilter;
        this.tokenBlacklistService = tokenBlacklistService;
    }
    @Autowired
    UserService userService;

//    @Autowired
//    private LoginSuccessHandler loginSuccessHandler;

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder((passwordEncoder()));   }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http, AccessDeniedHandler accessDeniedHandler, JwtTokenUtil jwtTokenUtil) throws Exception {

        http.cors(Customizer.withDefaults())
        .csrf(csrf->csrf.disable())
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers(HttpMethod.OPTIONS).permitAll()
                        .requestMatchers("/api/auth/**").permitAll() // 允许所有人访问登录页面
                        .requestMatchers("/error").permitAll()
                        .requestMatchers("/api/chat/stream/**").hasAnyRole("USER", "ADMIN")
                        .requestMatchers("/api/user/**").hasAnyRole("USER","ADMIN")
                        .anyRequest().permitAll()

                ).sessionManagement(session -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                .securityContext(context -> context
                         .securityContextRepository(securityContextRepository()) // 自定义上下文保存
                )
                .logout(logout -> logout
                        .logoutUrl("/api/auth/logout")
                        .addLogoutHandler((request, response, auth) -> {
                            String token = extractTokenFromHeader(request);
                           // System.out.println("55555555555555555555555555555555555555"+token);
                            jwtTokenUtil.invalidateToken(token);
                        })
                        .logoutSuccessHandler((request, response, auth) -> {
                            response.setStatus(HttpStatus.OK.value());
                        })
                )
                .addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class)
                .exceptionHandling(exception -> exception
                        .authenticationEntryPoint((req, res, ex) ->
                                res.sendError(HttpStatus.UNAUTHORIZED.value(), "Unauthorized")
                        )
                )
                 ;

        return http.build();
    }
    // 自定义上下文存储（解决异步问题）
    @Bean
    public SecurityContextRepository securityContextRepository() {
        return new DelegatingSecurityContextRepository(
                new RequestAttributeSecurityContextRepository(),
                new NullSecurityContextRepository()
        );
    }
    /**
     * 由于5.x版本之后默认启用了委派密码编译器，
     * 因而按照以往的方式设置内存密码将会读取异常，
     * 所以需要暂时将密码编码器设置为 NoOpPasswordEncoder
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
    // Standard header extraction
    private String extractTokenFromHeader(HttpServletRequest request) {
        String header = request.getHeader("Authorization");
       // System.out.println(header);
        if (header != null && header.startsWith("Bearer ")) {
            return header.substring(7);
        }
        return null;
    }
}
